local table_insert = table.insert
local math_random = math.random
local math_floor = math.floor

local TYPE_SINGLE_5_10 = 1     --单牌最大牌范围在5~10
local TYPE_SINGLE_J_K = 2      --单牌最大牌范围在J_K
local TYPE_SINGLE_A = 3        --单牌最大牌为A
local TYPE_DUIZI_29 = 4        --对子29
local TYPE_DUIZI_10A = 5       --对子10A
local TYPE_A23_789 = 6         --顺子A23-789
local TYPE_8910_QKA = 7        --顺子8910-QKA
local TYPE_JINHUA_5_10 = 8     --金花最大牌在5~10
local TYPE_JINHUA_J_A = 9      --金花最大牌在J~A
local TYPE_SHUNJIN = 10        --顺金
local TYPE_BAOZI = 11          --豹子

local zjh_rule = require "zhajinhua.zjh_rule"
local util = require "util"

local M = {}

local function get_compensation_type(uid,zjh_instance)
    local tile_list = zjh_instance:get_player_tile_list(uid)
    local type = zjh_rule.get_card_type(tile_list)
    if type == zjh_rule.CT_BAO_ZI then
        return TYPE_BAOZI                  --豹子
    end
    if type == zjh_rule.CT_SHUN_JIN then
        return TYPE_SHUNJIN                --顺金
    end
   
    if type == zjh_rule.CT_JIN_HUA then    
        local have_J_A
        for _,card_id in pairs(tile_list) do
            local value = zjh_rule.get_card_logic_value(card_id)
            if value >= 11 and value <= 14 then
                have_J_A = true
            end
        end
        if have_J_A then
            return TYPE_JINHUA_J_A       --金花最大牌在J~A
        end
        return TYPE_JINHUA_5_10          --金花最大牌在5~10
    end
    
    if type == zjh_rule.CT_SHUN_ZI then
        local sum = zjh_rule.extract_card_number(tile_list[1])+zjh_rule.extract_card_number(tile_list[2])+zjh_rule.extract_card_number(tile_list[3])
        if sum >= 6 and sum <= 24 then    --123~789 
            return TYPE_A23_789          --顺子A23-789
        end    
        return TYPE_8910_QKA             --顺子8910-QKA
    end

    if type == zjh_rule.CT_DOUBLE then    
        local card_count_map = {}
        for _,card_id in pairs(tile_list) do
            local value = zjh_rule.get_card_logic_value(card_id)
            card_count_map[value] = (card_count_map[value] or 0) + 1
        end

        for value,count in pairs(card_count_map) do
            if count >=2 and value >=2 and value <= 9 then
                return TYPE_DUIZI_29       --对子29
            end
        end

        return TYPE_DUIZI_10A              --对子10A
    end

    local have_J_K, have_A
    if type == zjh_rule.CT_SINGLE then   
        for _,card_id in pairs(tile_list) do
            local value = zjh_rule.get_card_logic_value(card_id)
            if value == 14 then
                have_A = true
            elseif  value >= 11 and value <= 13 then
                have_J_K = true
            end
        end
        if have_A then
            return TYPE_SINGLE_A            --单牌最大牌为A
        elseif have_J_K then
            return TYPE_SINGLE_J_K          --单牌最大牌范围在J_K         
        end

        return TYPE_SINGLE_5_10             --单牌最大牌范围在5~10
    end

    return TYPE_SINGLE_5_10
end

local function create_msg(pb_name,msg)
    local req_msg = {}
    req_msg.pb_name = pb_name
    req_msg.msg = msg
    return req_msg
end

--------------------机器人行为-----------------
--请求看牌
local function req_look_card(robot,req_msg_list)
    if robot.game_status.can_look then
        local req_msg = create_msg('REQ_LOOK_CARD',{})
        table_insert(req_msg_list, req_msg)
        return true
    end

    return false
end

--请求跟注
local function req_add_score(robot,req_msg_list,add_score)
    local add_type
    local bet_score = robot.game_status.bet_score
    if not bet_score then
        return false
    end
    local zjh_instance = robot.zjh_instance
    if add_score then    --加注
        add_type = 1  
        bet_score = add_score
    else                 --跟注
        add_type = 2
    end

    --如果有全压，则add_type改为3
    if zjh_instance:is_pre_quanya() then
        add_type = 3
    end

    --print("===========req_add_score========",robot.uid,robot.player_info.coins,add_type,add_score)
    local req_msg = create_msg('REQ_ADD_SCORE',{bet_score = add_score, add_type = add_type})
    table_insert(req_msg_list,req_msg)

    return true
end

--请求比牌
local function req_compare_card(robot,req_msg_list)
    if robot.game_status.can_compare then
        local zjh_instance = robot.zjh_instance
        if zjh_instance:is_pre_quanya() then
            local req_msg = create_msg('REQ_ADD_SCORE',{bet_score = add_score, add_type = 3})
            table_insert(req_msg_list,req_msg)
        else
            local req_msg = create_msg('REQ_COMPARE_CARD',{is_force = false})
            table_insert(req_msg_list,req_msg)
        end
    else    --不能比牌就跟注
        req_add_score(robot,req_msg_list)
    end
end

--请求跟牌型最大的玩家比牌
local function req_compare_card_with_best(robot,req_msg_list)
    if robot.game_status.can_compare then
        local zjh_instance = robot.zjh_instance
        local req_msg = create_msg('REQ_COMPARE_BEST_CARD',{is_force = false})
        table_insert(req_msg_list,req_msg)
    else    --不能比牌就跟注
        req_add_score(robot,req_msg_list)
    end
end

--请求弃牌(弃牌之前一定要已经看了牌)
local function req_give_up(robot,req_msg_list)
   -- print("==========mmmmmmmmreq_give_up=====",robot.uid)
    local zjh_instance = robot.zjh_instance

    --如果是系统赢并且是最大的牌，则跟注或者比牌
    if robot.system_win and robot.uid == zjh_instance:get_best_card_uid() then
       -- print("special give up",robot.uid)
        if not robot.game_status.bet_score or math_random(1,100) < 50 then
         --   print("special give up req_compare_card")
            req_compare_card(robot,req_msg_list)
            robot.compare = true
        else
       --     print("special give up req_add_score")
            req_add_score(robot,req_msg_list)
        end
        return
    end

    
    if not zjh_instance:is_ming_pai(robot.uid) then
     --   print("========look",robot.uid)
        robot.will_give_up = true
        req_look_card(robot,req_msg_list)
        return
    end

    local req_msg = create_msg('REQ_GIVE_UP',{})
    table_insert(req_msg_list, req_msg)
end

--下一动作的比例{跟注，加注，比牌，找最大玩家比牌，弃牌}
local function get_act_index(robot,action)
    local zjh_instance = robot.zjh_instance
    local player_num = zjh_instance:get_valid_player_num()
    local sum = 0
    local action_cnf 

    if player_num > 2 then
        action_cnf = action.greater_than_two
    else 
        action_cnf = action.equal_to_two
    end

    for _, v in pairs(action_cnf.rate) do
        sum = sum + v 
    end
    local rand = math_random(1,sum)
    local curr = 0
    for index,v in pairs(action_cnf.rate) do
        curr = curr + v
        if rand <= curr then
            if index == 1 then  --如果随机的是跟注，则随机出跟注多少轮
                robot.genzhu_limit = math_random(action_cnf.genzhu[1],action_cnf.genzhu[2])
            end

            if index == 3 then  --如果是比牌，则后面轮到操作时均为比牌
                robot.compare = true
            end
            return index
        end
    end

end

local function do_limit_action(robot,req_msg_list)
    --print("do_limit_action=======",robot.uid)
    local rate = robot.limit_action
    local sum = 0
    for _, v in pairs(rate) do
        sum = sum + v 
    end

    local action_index = 1
    local rand = math_random(1,sum)
    local curr = 0
    for index,v in pairs(rate) do
        curr = curr + v
        if rand <= curr then
            action_index = index
            break
        end
    end

    if action_index == 1 then
        req_give_up(robot,req_msg_list)
    elseif action_index == 2 then
        req_compare_card_with_best(robot,req_msg_list)
    elseif action_index == 3 then
        req_compare_card(robot,req_msg_list)
    end
end

--看牌机器人跟注行为策略
local function look_act_bet(robot,req_msg_list,action)
    --当机器人金币不足时，正常随机，随机到弃牌时，选择弃牌，随机到其他时选择比牌
    local zjh_instance = robot.zjh_instance
    local curr_coins = robot.player_info.coins
    local bet_score = zjh_instance:get_can_bet_score(robot.uid)
    local room_dingzhu = zjh_instance:get_ding_zhu(robot.uid)
    local is_succ = true
    local add_score

    --检查是否超过下注最大值
    local total_score = zjh_instance:get_player_bet_score(robot.uid)
    --print("============zjh_strategy look_card_logic======",robot.uid,total_score,bet_score + total_score,"ssss",robot.bet_limit)
    if bet_score + total_score > robot.bet_limit then
        return do_limit_action(robot,req_msg_list)
    end

    --有10%的概率加注1~3倍
    if math_random(1,100) <= 10 then
        local score = bet_score * math_random(2,4)
        if curr_coins >= score and score <= room_dingzhu then
            add_score = score
        end
    end

    if curr_coins >= bet_score and bet_score <= room_dingzhu then
        is_succ = req_add_score(robot,req_msg_list,add_score)
    end
    
    if not is_succ or curr_coins < bet_score or bet_score > room_dingzhu then
        local new_index = get_act_index(robot,action)     --再随机一次行为
        --print("=======mmmmmmmmlook_act_bet curr_coins====",robot.uid,curr_coins,new_index)
        if new_index == 5 then     --弃牌
            req_give_up(robot,req_msg_list)
        else
            req_compare_card(robot,req_msg_list)
        end
    end
end

--焖牌机器人跟注行为策略
local function nolook_act_bet(robot,req_msg_list)
    --在焖牌环节，若机器人金币不足不够跟注时，直接看牌
    local zjh_instance = robot.zjh_instance
    local bet_score = zjh_instance:get_can_bet_score(robot.uid)
    local room_dingzhu = zjh_instance:get_ding_zhu(robot.uid)
    local total_score = zjh_instance:get_player_bet_score(robot.uid)
    --print("total_score-----=====",robot.uid,total_score)
    if robot.player_info.coins >= bet_score and bet_score <= room_dingzhu then
        --确定闷牌后有10%的几率加注1~3倍
        local is_jiazhu = zjh_instance:get_curr_jiazhu_record()
        if not is_jiazhu and math_random(1,100) <= 10 then
            local add_score = bet_score * (math_random(1,3))
            if robot.player_info.coins > add_score and add_score <= room_dingzhu then
                return req_add_score(robot,req_msg_list,add_score)
            end
        end
        req_add_score(robot,req_msg_list)
    else
        req_look_card(robot,req_msg_list)
    end
end

--机器人加注行为策略
local function robot_act_add(robot,req_msg_list,is_look,action)
    --当机器人随机到“加注”时，加注加1~3倍底注
    local zjh_instance = robot.zjh_instance
    local room_dingzhu = zjh_instance:get_ding_zhu(robot.uid)
    local bet_score = zjh_instance:get_can_bet_score(robot.uid)

    if robot.player_info.coins < bet_score or bet_score >= room_dingzhu then     --钱不够跟注
        if is_look then
            look_act_bet(robot,req_msg_list,action)
        else
            nolook_act_bet(robot,req_msg_list)
        end 
    else
        local room_dizhu = zjh_instance:get_room_dizhu()  --房间底注
        
        local add_score = 0
        if is_look then
            add_score = room_dizhu * math_random(1,3)*2 + bet_score
        else
            add_score = room_dizhu * math_random(1,3) + bet_score
        end
        if add_score > room_dingzhu then                --加注额度不能超过顶住
            add_score = room_dingzhu
        end
        if robot.player_info.coins < add_score then     --身上的钱不够加注金额，加注身上所有的钱
            add_score = nil
        end
        req_add_score(robot,req_msg_list,add_score)
    end
end

local function set_bet_limit(robot,action)
    local zjh_instance = robot.zjh_instance
    local dizhu = zjh_instance:get_room_dizhu()
    local range = action.bet_limit.range
    robot.bet_limit = dizhu * (math_random(range[1],range[2]))
    robot.limit_action = action.bet_limit.action_rate

  --  print("robot.bet_limit",robot.bet_limit,tostring_r(robot.limit_action))
end

--看牌逻辑
local function look_card_logic(robot,req_msg_list)
    local zjh_instance = robot.zjh_instance
    local look_AI = global_configs.zjh_robotAI.look

    local type = get_compensation_type(robot.uid,zjh_instance)
    local look_cnf = look_AI[type]
    local action
    if robot.uid == zjh_instance:get_best_card_uid() then
        action = look_cnf.big
    else
        action = look_cnf.small
    end
    if not robot.analyse_logic then
        --设置机器人单局投入最大值
        set_bet_limit(robot,action)
        
        local act_index = get_act_index(robot,action)       --根据权重选择一个行为比率，随机一个行为
       -- print("============zjh_strategy look_card_logic======",robot.uid,type,act_index,robot.genzhu_limit,tostring_r(zjh_instance:get_player_tile_list(robot.uid)))

        if act_index == 1 then      --跟注
            look_act_bet(robot,req_msg_list,action)
            robot.genzhu = (robot.genzhu or 0) + 1
        elseif act_index == 2 then  --加注
            robot_act_add(robot,req_msg_list,true,action)
        elseif act_index == 3 then  --比牌
            req_compare_card(robot,req_msg_list)
        elseif act_index == 4 then  --找牌型最大玩家比牌
            req_compare_card_with_best(robot,req_msg_list)
        else                        --弃牌
            req_give_up(robot,req_msg_list)
        end

        robot.analyse_logic = true
    else
        if not robot.genzhu_limit then
            -- if robot.compare then   --比牌
                req_compare_card(robot,req_msg_list)
            -- else
            --     req_give_up(robot,req_msg_list)
            -- end
        elseif robot.genzhu_limit and (not robot.genzhu or robot.genzhu < robot.genzhu_limit) then
            look_act_bet(robot,req_msg_list,action)
            robot.genzhu = (robot.genzhu or 0) + 1
        else
            req_compare_card(robot,req_msg_list)
        end
    end
end

--焖牌逻辑
local function nolook_card_logic(robot,req_msg_list)
    local zjh_instance = robot.zjh_instance
    local nolook_AI = global_configs.zjh_robotAI.no_look
    local curr_round = zjh_instance:get_run_round()
    local rate = nolook_AI.round_rate[curr_round]
    local roomdata = global_configs.roomdata[zjh_instance.table_type]
    if not rate then
        rate = nolook_AI.menpai_rate or 0
    end

    if math_random(1,100) <= rate then
        nolook_act_bet(robot,req_msg_list)
    else
        if roomdata.max_look_round > curr_round then
            errlog("curr_round","roomdata.max_look_round :",roomdata.max_look_round,"nolook_AI.round_rate[curr_round]:",nolook_AI.round_rate[curr_round])
            nolook_act_bet(robot,req_msg_list)
            return
        end  
        req_look_card(robot,req_msg_list)
    end
end

function M.look_analyse_play(robot)
    local zjh_instance = robot.zjh_instance
    local req_msg_list = {}

    -- if not zjh_instance:is_my_turn(robot.uid) then
    --     return
    -- end

    if robot.game_status.force_compare_uid then     --超过最大轮数
        --req_compare_card(robot,req_msg_list)
        return
    end

    if robot.will_give_up then
        req_give_up(robot,req_msg_list)
        robot.will_give_up = false
    else
        look_card_logic(robot,req_msg_list)       --走看牌逻辑
    end

    return req_msg_list
end

function M.analyse_play(robot)
    local zjh_instance = robot.zjh_instance
    if not zjh_instance then return end

    local req_msg_list = {}
    -- if not zjh_instance:is_my_turn(robot.uid) then
    --     return
    -- end

    if robot.game_status.force_compare_uid then     --超过最大轮数
        --req_compare_card(robot,req_msg_list)
        dbglog("超过最大轮数")
        return
    end

    --看了牌走看牌逻辑，没看牌，走焖牌
    if zjh_instance:is_ming_pai(robot.uid) then
        look_card_logic(robot,req_msg_list)       --走看牌逻辑
    else
        print("================nolook_card_logic")
        nolook_card_logic(robot,req_msg_list) --焖牌逻辑
    end

    return req_msg_list
end

return M